package ti.me.seek2chat.leancloud

import android.util.Log
import android.content.Context
import cn.leancloud.LeanCloud
import cn.leancloud.LCObject
import cn.leancloud.LCQuery
import cn.leancloud.LCUser
import io.reactivex.Observer
import io.reactivex.disposables.Disposable
import io.reactivex.exceptions.UndeliverableException
import io.reactivex.plugins.RxJavaPlugins
import ti.me.seek2chat.models.ChatMessage
import ti.me.seek2chat.models.User
import ti.me.seek2chat.utilities.Constants
import java.util.Properties
import kotlin.concurrent.fixedRateTimer

/**
 * LeanCloudService 是一个与 LeanCloud 后端服务进行交互的服务类。
 *
 * 这个类提供了与 LeanCloud 后端进行数据存储、查询等操作的方法。
 */
class LeanCloudService(context: Context) {
    init {
        //Initialize LeanCloud SDK
        val properties = Properties()
        try {
            val inputStream = context.assets.open("leancloud_config.properties")
            properties.load(inputStream)
        } catch (e: Exception) {
            e.printStackTrace()
        }
        val appId = properties.getProperty("appId")
        val appKey = properties.getProperty("appKey")
        LeanCloud.initialize(context, appId, appKey, "https://avoscloud.com")

        // 设置全局错误处理
        RxJavaPlugins.setErrorHandler { e ->
            if (e is UndeliverableException) {
                Log.e(
                    "LeanCloudService",
                    "Undeliverable exception received, not sure what to do",
                    e.cause
                )
            } else {
                Log.e("LeanCloudService", "Exception received", e)
            }
        }
    }


    /**
     * 用户注册方法
     *
     * @param name 用户名
     * @param email 用户的电子邮件
     * @param password 用户的密码
     * @param image 用户的头像图像
     * @param callback 注册结果的回调函数
     */
    fun signUp(
        name: String,
        email: String,
        password: String,
        image: String?,
        callback: (Boolean, String?, String?) -> Unit
    ) {
        val user = LCUser()
        user.username = name
        user.email = email
        user.password = password
        user.put(Constants.KEY_IMAGE, image)
        user.signUpInBackground().subscribe(object : Observer<LCUser> {
            override fun onNext(t: LCUser) {
                Log.d("LeanCloudService signUp", "onNext: $t")
                callback(true, t.objectId, null)
            }

            override fun onError(e: Throwable) {
                callback(false, null, e.message)
                Log.d("LeanCloudService signUp", "onError: ${e.message}")
            }

            override fun onSubscribe(d: Disposable) {}

            override fun onComplete() {}
        })
    }

    /**
     * 用户登录方法
     *
     * @param username 用户名
     * @param password 用户密码
     * @param callback 登录结果的回调函数
     */
    fun signIn(username: String, password: String, callback: (Boolean, LCUser?, String?) -> Unit) {
        LCUser.logIn(username, password).subscribe(object : Observer<LCUser> {
            override fun onNext(user: LCUser) {
                callback(true, user, null)
            }

            override fun onError(e: Throwable) {
                callback(false, null, e.message)
                Log.d("LeanCloudService signIn", "onError: ${e.message}")
            }

            override fun onSubscribe(d: Disposable) {}

            override fun onComplete() {}
        })
    }

    /**
     * 获取用户列表
     *
     * @param currentUserId 当前用户的 ID
     * @param callback 获取用户列表结果的回调函数
     */
    fun getUsers(currentUserId: String?, callback: (Boolean, List<User>?, String?) -> Unit) {
        val query = LCQuery<LCUser>("_User")
        query.findInBackground().subscribe(object : Observer<List<LCUser>> {
            override fun onNext(users: List<LCUser>) {
                val userList = users.filter { user -> user.objectId != currentUserId }.map { user ->
                    User(
                        name = user.username ?: "",
                        email = user.email ?: "",
                        image = user.getString(Constants.KEY_IMAGE) ?: "",
                        token = user.sessionToken ?: "",
                        id = user.objectId ?: ""
                    )
                }
                callback(true, userList, null)
            }

            override fun onError(e: Throwable) {
                callback(false, null, e.message)
                Log.e("LeanCloudService getUsers", e.message.toString())
            }

            override fun onSubscribe(d: Disposable) {}

            override fun onComplete() {}
        })
    }


    /**
     * 保存消息
     *
     * @param senderId 发送者 ID
     * @param receiverId 接收者 ID
     * @param message 消息内容
     */
    fun saveMessage(
        senderId: String, receiverId: String, message: String
    ) {
        val chat = LCObject(Constants.KEY_COLLECTION_CHAT)
        chat.put(Constants.KEY_SENDER_ID, senderId)
        chat.put(Constants.KEY_RECEIVER_ID, receiverId)
        chat.put(Constants.KEY_MESSAGE, message)
        chat.put(Constants.KEY_TIMESTAMP, System.currentTimeMillis())
        chat.saveInBackground().subscribe(object : Observer<LCObject> {
            override fun onNext(t: LCObject) {}

            override fun onError(e: Throwable) {}

            override fun onSubscribe(d: Disposable) {}

            override fun onComplete() {}
        })
    }

    /**
     * 监听消息
     *
     * @param receiverId 接收者 ID
     * @param callback 监听消息结果的回调函数
     */
    fun listenForMessages(
        receiverId: String, callback: (Boolean, List<LCObject>?, String?) -> Unit
    ) {
        val query = LCQuery<LCObject>(Constants.KEY_COLLECTION_CHAT)
        query.whereContainedIn(
            Constants.KEY_SENDER_ID, listOf(receiverId, LCUser.getCurrentUser().objectId)
        )
        query.whereContainedIn(
            Constants.KEY_RECEIVER_ID, listOf(receiverId, LCUser.getCurrentUser().objectId)
        )
        query.orderByAscending(Constants.KEY_TIMESTAMP)

        var lastTimestamp: Long? = null
        // 定期轮询查询数据, 5s
        fixedRateTimer("pollingTimer", false, 0L, 5000L) {
            if (lastTimestamp != null) {
                query.whereGreaterThan(Constants.KEY_TIMESTAMP, lastTimestamp)
            }

            query.findInBackground().subscribe(object : Observer<List<LCObject>> {
                override fun onNext(messages: List<LCObject>) {
                    if (messages.isNotEmpty()) {
                        lastTimestamp = messages.last().getLong(Constants.KEY_TIMESTAMP)
                    }
                    callback(true, messages, null)
                }

                override fun onError(e: Throwable) {
                    callback(false, null, e.message)
                }

                override fun onSubscribe(d: Disposable) {}

                override fun onComplete() {}
            })
        }
    }

    /**
     * 检查两个用户之间是否存在对话。
     *
     * @param senderId 发送者的用户ID。
     * @param receiverId 接收者的用户ID。
     * @param callback 回调函数
     */
    fun checkForConversionRemotely(
        senderId: String, receiverId: String, callback: (Boolean, String?) -> Unit
    ) {
        val query = LCQuery<LCObject>(Constants.KEY_COLLECTION_CONVERSATIONS)
        query.whereEqualTo(Constants.KEY_SENDER_ID, senderId)
        query.whereEqualTo(Constants.KEY_RECEIVER_ID, receiverId)
        query.findInBackground().subscribe(object : Observer<List<LCObject>> {
            override fun onNext(conversations: List<LCObject>) {
                if (conversations.isNotEmpty()) {
                    callback(true, conversations.first().objectId)
                } else {
                    callback(false, null)
                }
            }

            override fun onError(e: Throwable) {
                Log.e(
                    "LeanCloudService checkForConversionRemotely",
                    "Error checking for conversion: ${e.message}"
                )
                callback(false, null)
            }

            override fun onSubscribe(d: Disposable) {}

            override fun onComplete() {}
        })
    }

    /**
     * 添加会话
     *
     * @param conversion 会话信息
     */
    fun addConversion(conversion: HashMap<String, Any>) {
        val conversation = LCObject(Constants.KEY_COLLECTION_CONVERSATIONS)
        for ((key, value) in conversion) {
            conversation.put(key, value)
        }
        conversation.saveInBackground().subscribe(object : Observer<LCObject> {
            override fun onNext(t: LCObject) {}

            override fun onError(e: Throwable) {
                Log.e("LeanCloudService addConversion", "Error adding conversion: ${e.message}")
            }

            override fun onSubscribe(d: Disposable) {}

            override fun onComplete() {}
        })
    }

    /**
     * 更新会话
     *
     * @param conversionId 会话ID
     * @param message 最新消息
     */
    fun updateConversion(
        conversionId: String,
        message: String,
    ) {
        val conversations =
            LCObject.createWithoutData(Constants.KEY_COLLECTION_CONVERSATIONS, conversionId)
        conversations.put(Constants.KEY_LAST_MESSAGE, message)
        conversations.put(Constants.KEY_TIMESTAMP, System.currentTimeMillis())
        conversations.saveInBackground().subscribe(object : Observer<LCObject> {
            override fun onNext(t: LCObject) {}

            override fun onError(e: Throwable) {}

            override fun onSubscribe(d: Disposable) {}

            override fun onComplete() {}
        })
    }

    /**
     * 监听会话
     *
     * @param userId 用户ID
     * @param callback 回调函数，返回会话列表或错误信息
     */
    fun listenForConversations(
        userId: String, callback: (Boolean, List<ChatMessage>?, String?) -> Unit
    ) {
        val query1 = LCQuery<LCObject>(Constants.KEY_COLLECTION_CONVERSATIONS)
        query1.whereEqualTo(Constants.KEY_SENDER_ID, userId)
        val query2 = LCQuery<LCObject>(Constants.KEY_COLLECTION_CONVERSATIONS)
        query1.whereEqualTo(Constants.KEY_RECEIVER_ID, userId)
        val query = LCQuery.or(listOf(query1, query2))
        query.orderByDescending(Constants.KEY_TIMESTAMP)

        // 定期轮询查询数据, 5s
        fixedRateTimer("pollingTimer", false, 0L, 5000L) {
            query.findInBackground().subscribe(object : Observer<List<LCObject>> {
                override fun onNext(conversations: List<LCObject>) {
                    val chatMessages = conversations.map { conversation ->
                        val senderId = conversation.getString(Constants.KEY_SENDER_ID) ?: ""
                        val receiverId = conversation.getString(Constants.KEY_RECEIVER_ID) ?: ""
                        val chatMessage = ChatMessage(
                            senderId = senderId,
                            receiverId = receiverId,
                            message = conversation.getString(Constants.KEY_LAST_MESSAGE) ?: "",
                            dateTime = conversation.getString(Constants.KEY_TIMESTAMP) ?: "",
                            conversionId = if (userId == senderId) receiverId else senderId,
                            conversionName = if (userId == senderId) conversation.getString(
                                Constants.KEY_RECEIVER_NAME
                            ) ?: "" else conversation.getString(Constants.KEY_SENDER_NAME) ?: "",
                            conversionImage = if (userId == senderId) conversation.getString(
                                Constants.KEY_RECEIVER_IMAGE
                            ) ?: "" else conversation.getString(Constants.KEY_SENDER_IMAGE) ?: ""
                        )
                        chatMessage
                    }
                    callback(true, chatMessages, null)
                }

                override fun onError(e: Throwable) {
                    callback(false, null, e.message)
                }

                override fun onSubscribe(d: Disposable) {}

                override fun onComplete() {}
            })
        }
    }

    /**
     * 更新用户在线状态
     *
     * @param value 在线状态值，1 表示在线，0 表示离线
     */
    fun updateAvailability(value: Int) {
        val user = LCUser.currentUser()
        if (user != null) {
            user.put(Constants.KEY_AVAILABILITY, value)
            user.saveInBackground().subscribe()
        }
    }

    /**
     * 监听用户在线状态
     *
     * @param receiverId 接收者ID
     * @param callback 回调函数，返回在线状态或错误信息
     */
    fun listenAvailability(receiverId: String, callback: (Boolean, Int) -> Unit) {
        val query = LCQuery<LCUser>("_User")
        query.whereEqualTo("objectId", receiverId)
        // 定期轮询查询数据, 5s
        fixedRateTimer("pollingTimer", false, 0L, 5000L) {
            query.findInBackground().subscribe(object : Observer<List<LCUser>> {
                override fun onNext(users: List<LCUser>) {
                    if (users.isNotEmpty()) {
                        callback(true, users.first().getInt(Constants.KEY_AVAILABILITY))
                    }
                }

                override fun onError(e: Throwable) {
                    callback(false, 0)
                }

                override fun onSubscribe(d: Disposable) {}

                override fun onComplete() {}
            })
        }
    }
}